classdef FS_L3 < PROBLEM
% <multi> <binary> <large/none> <expensive/none> 
% The feature selection problem
% The datasets are taken from the UCI machine learning repository in
% http://archive.ics.uci.edu/ml/index.php

    properties(Access = private)
        Data;       %TestData and TrainData
        Category;   % Output label set
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            % Load data
            OData = load('./DataSet/Madelon.txt');
            Fmin = min(OData(:,1:end-1),[],1);
            Fmax = max(OData(:,1:end-1),[],1);
            OData(:,1:end-1) = (OData(:,1:end-1)-repmat(Fmin,size(OData,1),1))./repmat(Fmax-Fmin,size(OData,1),1);
            obj.Category    = OData(:,end);
            obj.Data        = OData(:,1:end-1);
            % Parameter setting
            obj.M        = 2;
            obj.D        = size(obj.Data,2);
            obj.encoding = 4 + zeros(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,PopDec)
            PopDec = logical(PopDec);
            PopObj = zeros(size(PopDec,1),2);
            for i = 1 : size(PopObj,1)
                x=PopDec(i,:); 
                subx=find(x==1); 
                PopObj(i,1) =size(subx,2)/size(PopDec,2);  
                CVF = 3;
                % 初始化性能指标
                accuracy = zeros(CVF,1);
                % 进行K折交叉验证
                for j = 1:CVF
                % 生成训练集和测试集索引
                indices = crossvalind('Kfold',length(obj.Category),CVF);
                testIdx = (indices == j); 
                trainIdx = ~testIdx;
                % 提取训练集和测试集数据
                XTrain = obj.Data(trainIdx,:);
                YTrain = obj.Category(trainIdx);
                XTest  = obj.Data(testIdx,:);
                YTest  = obj.Category(testIdx);
                % 训练KNN分类器
                knnModel = fitcknn(XTrain,YTrain,'NumNeighbors',3);
                % 预测测试集并计算准确率
                [YPred,] = predict(knnModel,XTest);
                accuracy(j) = sum(YPred == YTest)/length(YTest);
                end
                % 输出平均准确率
                meanAccuracy = mean(accuracy);
                PopObj(i,2)  = meanAccuracy;         
            end             
        end
       
        
        %% Display a population in the objective space
        function DrawObj(obj,Population)
            Draw(Population.objs,{'Ratio of selected features','Classification Accuracy',[]});
        end
    end
end